package com.wbihua.common.metrics.metric.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.SafeConcurrentHashMap;
import com.wbihua.common.metrics.manager.MetricManager;
import com.wbihua.common.metrics.metric.EventMeterCounter;
import com.wbihua.common.metrics.type.EventCounterType;
import io.micrometer.core.instrument.Counter;

import java.util.List;

public class EventCounter implements EventMeterCounter {
    private static final SafeConcurrentHashMap<List<String>, Counter> POOL = new SafeConcurrentHashMap<>();
    private Counter counter;

    private final EventCounterType counterType;
    private MetricManager metricManager;

    public EventCounter(EventCounterType counterType) {
        this.counterType = counterType;
    }

    public EventCounter(EventCounterType counterType, MetricManager metricManager) {
        this(counterType);
        this.metricManager = metricManager;
    }

    @Override
    public void registry(MetricManager metricManager) {
        this.counter =metricManager.getMetricRegistry().counter(getCounterType().getName(), metricManager.getTags());
    }

    @Override
    public <T> T getMeter() {
        return (T)this.counter;
    }

    @Override
    public <T> T getMeter(String... tagValues) {
        return (T)POOL.get(tagValues);
    }

    @Override
    public EventCounterType getCounterType() {
        return this.counterType;
    }

    @Override
    public void increment(double count) {
        counter.increment(count);
    }

    @Override
    public void increment(double count, String... labelValues) {
        getCounter(labelValues).increment(count);
    }

    private Counter getCounter(String[] tagValues) {
        if (tagValues.length != counterType.getTags().length) {
            throw new IllegalArgumentException("Incorrect number of labels.");
        }
        for (String value: tagValues) {
            if (value == null) {
                throw new IllegalArgumentException("Label cannot be null.");
            }
        }
        return POOL.computeIfAbsent(ListUtil.toList(tagValues), values -> {
            Counter.Builder builder = Counter.builder(counterType.getName());
            builder.tags(metricManager.getTags());
            String[] tage = counterType.getTags();
            for (int i = 0; i < values.size(); i++) {
                builder.tag(tage[i], values.get(i));
            }
            return builder .description(counterType.getDescription())
                    .baseUnit(counterType.getBaseUnit())
                    .register(metricManager.getMetricRegistry());
        });
    }
}
